package com.dsteiner.widgets.client;

import java.util.ArrayList;
import java.util.Date;
import java.util.Iterator;
import java.util.List;

import com.dsteiner.widgets.client.resources.WidgetsResources;
import com.google.gwt.animation.client.Animation;
import com.google.gwt.core.client.EntryPoint;
import com.google.gwt.dom.client.Document;
import com.google.gwt.dom.client.FrameElement;
import com.google.gwt.dom.client.StyleInjector;
import com.google.gwt.event.dom.client.BlurHandler;
import com.google.gwt.event.dom.client.ChangeHandler;
import com.google.gwt.event.dom.client.ClickHandler;
import com.google.gwt.event.dom.client.ErrorHandler;
import com.google.gwt.event.dom.client.FocusHandler;
import com.google.gwt.event.dom.client.HasAllMouseHandlers;
import com.google.gwt.event.dom.client.HasBlurHandlers;
import com.google.gwt.event.dom.client.HasChangeHandlers;
import com.google.gwt.event.dom.client.HasClickHandlers;
import com.google.gwt.event.dom.client.HasErrorHandlers;
import com.google.gwt.event.dom.client.HasFocusHandlers;
import com.google.gwt.event.dom.client.HasKeyDownHandlers;
import com.google.gwt.event.dom.client.HasKeyPressHandlers;
import com.google.gwt.event.dom.client.HasKeyUpHandlers;
import com.google.gwt.event.dom.client.HasLoadHandlers;
import com.google.gwt.event.dom.client.HasMouseDownHandlers;
import com.google.gwt.event.dom.client.HasMouseMoveHandlers;
import com.google.gwt.event.dom.client.HasMouseOutHandlers;
import com.google.gwt.event.dom.client.HasMouseOverHandlers;
import com.google.gwt.event.dom.client.HasMouseUpHandlers;
import com.google.gwt.event.dom.client.KeyDownHandler;
import com.google.gwt.event.dom.client.KeyPressHandler;
import com.google.gwt.event.dom.client.KeyUpHandler;
import com.google.gwt.event.dom.client.LoadHandler;
import com.google.gwt.event.dom.client.MouseDownHandler;
import com.google.gwt.event.dom.client.MouseMoveHandler;
import com.google.gwt.event.dom.client.MouseOutHandler;
import com.google.gwt.event.dom.client.MouseOverHandler;
import com.google.gwt.event.dom.client.MouseUpHandler;
import com.google.gwt.event.dom.client.MouseWheelHandler;
import com.google.gwt.event.shared.HandlerRegistration;
import com.google.gwt.i18n.client.HasDirection;
import com.google.gwt.user.client.Command;
import com.google.gwt.user.client.DOM;
import com.google.gwt.user.client.Element;
import com.google.gwt.user.client.Event;
import com.google.gwt.user.client.Timer;
import com.google.gwt.user.client.ui.AbsolutePanel;
import com.google.gwt.user.client.ui.Button;
import com.google.gwt.user.client.ui.CaptionPanel;
import com.google.gwt.user.client.ui.CheckBox;
import com.google.gwt.user.client.ui.ClickListener;
import com.google.gwt.user.client.ui.Composite;
import com.google.gwt.user.client.ui.DelegatingClickListenerCollection;
import com.google.gwt.user.client.ui.DisclosureHandler;
import com.google.gwt.user.client.ui.DisclosurePanel;
import com.google.gwt.user.client.ui.FileUpload;
import com.google.gwt.user.client.ui.FiresDisclosureEvents;
import com.google.gwt.user.client.ui.FlexTable;
import com.google.gwt.user.client.ui.FlowPanel;
import com.google.gwt.user.client.ui.FocusPanel;
import com.google.gwt.user.client.ui.Focusable;
import com.google.gwt.user.client.ui.FormPanel;
import com.google.gwt.user.client.ui.Frame;
import com.google.gwt.user.client.ui.HTML;
import com.google.gwt.user.client.ui.HTMLPanel;
import com.google.gwt.user.client.ui.HasAnimation;
import com.google.gwt.user.client.ui.HasHTML;
import com.google.gwt.user.client.ui.HasHorizontalAlignment;
import com.google.gwt.user.client.ui.HasName;
import com.google.gwt.user.client.ui.HasText;
import com.google.gwt.user.client.ui.HasWidgets;
import com.google.gwt.user.client.ui.HasWordWrap;
import com.google.gwt.user.client.ui.HorizontalPanel;
import com.google.gwt.user.client.ui.Image;
import com.google.gwt.user.client.ui.IndexedPanel;
import com.google.gwt.user.client.ui.InlineHTML;
import com.google.gwt.user.client.ui.PasswordTextBox;
import com.google.gwt.user.client.ui.PopupListener;
import com.google.gwt.user.client.ui.PopupPanel;
import com.google.gwt.user.client.ui.RadioButton;
import com.google.gwt.user.client.ui.RichTextArea;
import com.google.gwt.user.client.ui.RootPanel;
import com.google.gwt.user.client.ui.ScrollPanel;
import com.google.gwt.user.client.ui.SimplePanel;
import com.google.gwt.user.client.ui.SourcesChangeEvents;
import com.google.gwt.user.client.ui.SourcesScrollEvents;
import com.google.gwt.user.client.ui.TextArea;
import com.google.gwt.user.client.ui.TextBox;
import com.google.gwt.user.client.ui.UIObject;
import com.google.gwt.user.client.ui.Widget;
import com.google.gwt.user.client.ui.FormPanel.SubmitCompleteHandler;
import com.google.gwt.user.client.ui.FormPanel.SubmitHandler;
import com.google.gwt.user.client.ui.HasHorizontalAlignment.HorizontalAlignmentConstant;
import com.google.gwt.user.client.ui.HasVerticalAlignment.VerticalAlignmentConstant;
import com.google.gwt.user.client.ui.PopupPanel.PositionCallback;
import com.google.gwt.user.client.ui.RichTextArea.BasicFormatter;
import com.google.gwt.user.client.ui.RichTextArea.ExtendedFormatter;
import com.google.gwt.user.client.ui.impl.FormPanelImplHost;
import com.google.gwt.user.datepicker.client.DateBox;
import com.google.gwt.user.datepicker.client.DatePicker;

public class Widgets implements EntryPoint{

	public interface IWidgetBuilder {
		public IWidget createWidget(Object model);
	}
	
	public interface IWidget{
		boolean isAttached();
		void setVisible(boolean visible);
		boolean isVisible();
		public int getAbsoluteLeft();
		public int getAbsoluteTop();
		public int getOffsetHeight();
		public int getOffsetWidth();
		public void setHeight(String height);
		public void setWidth(String width);
		public void setStyleName(String styleName);
		public void removeStyleName(String styleName);
		public String getStyleName();
		void addStyleDependentName(String string);
		void addStyleName(String string);
		void removeFromParent();
		void setSize(String width, String height);
		void setPixelSize(int width, int height);
		UIObject getParent();
	}
	
	public interface IFrame extends IWidget{
		public void setUrl(String url);
		public String getUrl();
		public String getFrameUrl();
	}
	
	public interface IFocusWidget extends IWidget, HasClickHandlers, 
    	HasKeyDownHandlers, HasKeyPressHandlers, HasKeyUpHandlers, HasFocusHandlers, 
    	HasBlurHandlers, Focusable{
	}
	
	public interface IFocusPanel extends IFocusWidget, HasMouseOverHandlers, HasMouseOutHandlers, 
	HasMouseDownHandlers, HasMouseMoveHandlers, HasMouseUpHandlers{

		void setIWidget(IWidget widget);
	}
	
	public interface IScrollPanel extends ISimplePanel, SourcesScrollEvents{

		int getScrollPosition();

		void setScrollPosition(int scrollPosition);
	}
	
	public interface ITimer{

		void cancel();

		void schedule(int ms);
		
		public void setCommand(Command command);

		void scheduleRepeating(int ms);		
	}
	
	public interface IPopupWidget extends IWidget{
		public void show(int x, int y);
		public void hide();
		public void addPopupListener(PopupListener popupListener);
		public void removePopupListener(PopupListener popupListener);
		public void setWidget(IWidget widget);
	}
	
	public interface IImage extends IWidget, 
    HasLoadHandlers, HasErrorHandlers, HasClickHandlers,
    HasAllMouseHandlers{

		void setUrl(String url);

		Image getImage();

		String getUrl();

		int getWidth();
		int getHeight();
		MediaPicture getMediaPicture();
		
		void setMediaPicture(MediaPicture mediaPicture, boolean showLowResolution);

		void setTitle(String title);
	}
	
	public static class MediaPicture{
		private String lowResImage;
		private String highResImage;
		private String description;
		public static final String NO_IMAGE_URL = "/includes/templates/dn_hp/css/map_images/no_image.png";
		
		public MediaPicture(String lowResImage, String highResImage, String description) {
			this.lowResImage = lowResImage;
			this.highResImage = highResImage;
			this.description = description;
		}
		@Override
		public boolean equals(Object obj) {
			if(obj == null)
				return false;
			if(!(obj instanceof MediaPicture))
				return false;
			MediaPicture other = (MediaPicture) obj;
			return other.highResImage.equals(highResImage) && other.lowResImage.equals(lowResImage);
		}
		public String getDescription() {
			return description;
		}
		public String getHighResImage() {
			return highResImage != null ? highResImage : NO_IMAGE_URL;
		}
		public String getLowResImage() {
			return lowResImage != null ? lowResImage : NO_IMAGE_URL;
		}
		@Override
		public String toString() {
			return highResImage+"|"+lowResImage+"|"+description;
		}
	}
	
	
	public interface IHTML extends HasHTML, IWidget, HasHorizontalAlignment,
	HasText, HasWordWrap, HasDirection, HasClickHandlers, HasMouseOverHandlers, HasMouseOutHandlers{

		void setEnable(boolean enable);

		boolean isEnable();
	}

	public interface IFlowPanel extends IIndexedPanel{
	}
	
	public interface ISimplePanel extends IPanel{

		void setWidget(IWidget widget);

		Widget getWidget();

		IWidget getIWidget();
	}
	
	public interface IPanel extends HasWidgets, IWidget{
		void add(IWidget widget);

		void clear();
	}
	public interface IIndexedPanel extends IPanel, IndexedPanel{
	}
	
	public interface IHorizontalPanel extends IPanel{
	}
	
	public interface IFlexTable extends IPanel{

		int getRowCount();

		void removeRow(int row);

		void setWidget(int column, int row, IWidget rowWidget);

		Widget getWidget(int column, int row);

		void setAlignment(int row, int column, HorizontalAlignmentConstant horizontalAlign,
				VerticalAlignmentConstant verticalAlign);

		void setWidget(int column, int row, Widget widget);

		int getCellCount(int i);
	}
	
	public interface IAbsolutePanel extends IWidget, IPanel{

		void setWidgetPosition(IWidget widget, int left, int top);

		void add(IWidget widget, int left, int top);

		void remove(IWidget widget);

		int getWidgetLeft(IWidget widget);
		
		int getWidgetTop(IWidget widget);
	}
	
	public interface IHidden extends HasName, IWidget{
		  public void setValue(String value);
		  public String getValue();
	}
	
	public interface IFormPanel extends IWidget, FormPanelImplHost{
		  public void submit();

		public HandlerRegistration addSubmitCompleteHandler(SubmitCompleteHandler handler);
		public HandlerRegistration addSubmitHandler(SubmitHandler handler);
		public void setAction(String url);
		public String getAction();
		public void setEncoding(String encodingType); 
		public void setMethod(String method);
	}
	
	public interface SelectionInput extends HasName, HasHTML, IFocusWidget, IWidget{
		public boolean isChecked();
		public void setChecked(boolean checked);
		public void setEnabled(boolean enable);
		public boolean isEnabled();
	}
	
	public interface TextInput extends 
    HasText, HasName, IFocusWidget, IWidget, HasChangeHandlers{

		void selectAll();
		public void setEnabled(boolean enabled);
		public void setCursorPos(int pos);
	}
	
	public interface PrefilledTextInput extends TextInput{
		public String getDefaultText();
		public void setDefaultText(String defaultText);
		public void showDefaultText();
	}

	public interface IButton extends IFocusWidget, HasHTML{

		void setEnabled(boolean enabled);
	}
	
	public static class WidgetExt extends Widget implements IWidget{
	}
	
	public static class FlowPanelExt extends FlowPanel implements IFlowPanel{
		public void add(IWidget widget) {
			add((Widget)widget);
		}
	}
	
	public static class PasswordTextBoxExt extends PasswordTextBox implements TextInput{
	}

	public interface IHTMLPanel extends IPanel{
		public void add(Widget widget, String id);
		public void add(IWidget widget, String id);
	}
	public static class HTMLPanelExt extends HTMLPanel implements IHTMLPanel{
		public HTMLPanelExt(String html) {
			super(html);
		}

		public void add(IWidget widget) {
			super.add((Widget) widget);
		}

		public void add(IWidget widget, String id) {
				super.add((Widget)widget, id);
		}
	}
	
	public static class AbsolutePanelExt extends AbsolutePanel implements IAbsolutePanel{
		public void add(IWidget widget) {
			super.add((Widget)widget);
		}

		public void remove(IWidget widget) {
			super.remove((Widget) widget);
		}

		public int getWidgetLeft(IWidget widget) {
			return super.getWidgetLeft((Widget)widget);
		}

		public int getWidgetTop(IWidget widget) {
			return super.getWidgetTop((Widget)widget);
		}

		public void add(IWidget widget, int left, int top) {
			super.add((Widget)widget, left, top);
		}

		public void setWidgetPosition(IWidget widget, int left, int top) {
			super.setWidgetPosition((Widget)widget, left, top);
		}
	}
	
	public static class RootPanelExt implements IAbsolutePanel{
		private final RootPanel rootPanel;
		public RootPanelExt(RootPanel rootPanel) {
			if(rootPanel == null)
				throw new IllegalStateException("Root panel can't be null");
			this.rootPanel = rootPanel;
		}
		public void addStyleDependentName(String styleSuffix) {
			rootPanel.addStyleDependentName(styleSuffix);
		}
		public void addStyleName(String style) {
			rootPanel.addStyleName(style);
		}
		public final void ensureDebugId(String id) {
			rootPanel.ensureDebugId(id);
		}
		public boolean equals(Object obj) {
			return rootPanel.equals(obj);
		}
		public int getAbsoluteLeft() {
			return rootPanel.getAbsoluteLeft();
		}
		public int getAbsoluteTop() {
			return rootPanel.getAbsoluteTop();
		}
		public Element getElement() {
			return rootPanel.getElement();
		}
		public int getOffsetHeight() {
			return rootPanel.getOffsetHeight();
		}
		public int getOffsetWidth() {
			return rootPanel.getOffsetWidth();
		}
		public Widget getParent() {
			return rootPanel.getParent();
		}
		public String getStyleName() {
			return rootPanel.getStyleName();
		}
		public String getStylePrimaryName() {
			return rootPanel.getStylePrimaryName();
		}
		public String getTitle() {
			return rootPanel.getTitle();
		}
		public Widget getWidget(int index) {
			return rootPanel.getWidget(index);
		}
		public int getWidgetCount() {
			return rootPanel.getWidgetCount();
		}
		public int getWidgetIndex(Widget child) {
			return rootPanel.getWidgetIndex(child);
		}
		public int getWidgetTop(Widget w) {
			return rootPanel.getWidgetTop(w);
		}
		public int hashCode() {
			return rootPanel.hashCode();
		}
		public boolean isAttached() {
			return rootPanel.isAttached();
		}
		public boolean isVisible() {
			return rootPanel.isVisible();
		}
		public void onBrowserEvent(Event event) {
			rootPanel.onBrowserEvent(event);
		}
		public void removeFromParent() {
			rootPanel.removeFromParent();
		}
		public void removeStyleDependentName(String styleSuffix) {
			rootPanel.removeStyleDependentName(styleSuffix);
		}
		public void removeStyleName(String style) {
			rootPanel.removeStyleName(style);
		}
		public void setHeight(String height) {
			rootPanel.setHeight(height);
		}
		public void setPixelSize(int width, int height) {
			rootPanel.setPixelSize(width, height);
		}
		public void setSize(String width, String height) {
			rootPanel.setSize(width, height);
		}
		public void setStyleName(String style) {
			rootPanel.setStyleName(style);
		}
		public void setStylePrimaryName(String style) {
			rootPanel.setStylePrimaryName(style);
		}
		public void setTitle(String title) {
			rootPanel.setTitle(title);
		}
		public void setVisible(boolean visible) {
			rootPanel.setVisible(visible);
		}
		public void setWidth(String width) {
			rootPanel.setWidth(width);
		}
		public void sinkEvents(int eventBitsToAdd) {
			rootPanel.sinkEvents(eventBitsToAdd);
		}
		public String toString() {
			return rootPanel.toString();
		}
		public void unsinkEvents(int eventBitsToRemove) {
			rootPanel.unsinkEvents(eventBitsToRemove);
		}
		public void add(Widget w, int left, int top) {
			rootPanel.add(w, left, top);
		}
		public void add(Widget w) {
			rootPanel.add(w);
		}
		public Iterator<Widget> iterator() {
			return rootPanel.iterator();
		}
		public boolean remove(int index) {
			return rootPanel.remove(index);
		}
		public boolean remove(Widget w) {
			return rootPanel.remove(w);
		}
		public void setWidgetPosition(Widget w, int left, int top) {
			rootPanel.setWidgetPosition(w, left, top);
		}
		public void add(IWidget widget) {
			add((Widget)widget);
		}
		public void remove(IWidget widget) {
			remove((Widget)widget);
		}
		public int getWidgetLeft(Widget widget) {
			return rootPanel.getWidgetLeft(widget);
		}
		public void clear() {
			rootPanel.clear();
		}
		public int getWidgetLeft(IWidget widget) {
			return getWidgetLeft((Widget)widget);
		}
		public int getWidgetTop(IWidget widget) {
			return getWidgetTop((Widget)widget);
		}
		public void add(IWidget widget, int left, int top) {
			add((Widget)widget, left, top);
		}
		public void setWidgetPosition(IWidget widget, int left, int top) {
			setWidgetPosition((Widget)widget, left, top);
		}
	}
	
	public static class SimplePanelExt extends SimplePanel implements ISimplePanel{
		public void add(IWidget widget) {
			add((Widget)widget);
		}
		public void setWidget(IWidget widget) {
			setWidget((Widget)widget);
		}
		public IWidget getIWidget() {
			return (IWidget) getWidget();
		}
	}
	
	public static class FlexTableExt extends FlexTable implements IFlexTable{

		public void setWidget(int column, int row, IWidget widget) {
			super.setWidget(row, column, (Widget) widget);
		}

		public void add(IWidget widget) {
			super.add((Widget) widget);
		}

		public void setAlignment(int row, int column,
				HorizontalAlignmentConstant horizontalAlign,
				VerticalAlignmentConstant verticalAlign) {
			getFlexCellFormatter().setAlignment(row, column, horizontalAlign, verticalAlign);
		}
	}

	public interface ICaptionPanel extends IPanel{
		
	}
	
	public static class CaptionPanelExt extends CaptionPanel implements ICaptionPanel{
		public CaptionPanelExt(String caption) {
			super(caption);
		}

		public void add(IWidget widget) {
			super.add((Widget) widget);
		}
	}
	
	public static class TimerExt extends Timer implements ITimer{
		private Command command;
		@Override
		public void run() {
			command.execute();
		}
		public void setCommand(Command command){
			this.command = command;
		}
	}
	
	public interface ISlidingAnimation extends IAnimation{
		void setSlideCount(int slideCount);
		int getSlideCount();
	}
	
	public interface IAnimation{
		public void onCancelIntern();
		void setCompleteCommand(Command completeCommand);
		void setUpdateCommand(Command updateCommand);
		void setCancelCommand(Command cancelCommand);
		void setStartCommand(Command command);
		public void onCompleteIntern();
		public void onUpdateIntern(double progress);
		public void onStartIntern();
		public double getProgress();
		public void setProgress(double progress);
	}
	
	public static class SlidingAnimation extends Animation implements ISlidingAnimation{
		private int slideCount;
		private double progress;
		private Command updateCommand;
		private Command cancelCommand;
		private Command completeCommand;
		private Command startCommand;
		public void setSlideCount(int slideCount) {
			this.slideCount = slideCount;
			if(slideCount != 0)
				run(1000);
		}
		public int getSlideCount() {
			return slideCount;
		}
		@Override
		protected void onStart() {
			onStartIntern();
		}
		public void onStartIntern() {
			if(startCommand != null)
				startCommand.execute();
		}
		@Override
		protected void onUpdate(double progress) {
			onUpdateIntern(progress);
		}
		public void onUpdateIntern(double progress) {
			setProgress(progress);
			if(updateCommand != null)
				updateCommand.execute();
		}
		public void onCancelIntern() {
			if(cancelCommand != null)
				cancelCommand.execute();
		}
		@Override
		protected void onCancel() {
			onCancelIntern();
		}
		public void onCompleteIntern() {
			if(completeCommand != null)
				completeCommand.execute();
		}
		@Override
		protected void onComplete() {
			onCompleteIntern();
		}
		public double getProgress() {
			return progress;
		}
		public void setCancelCommand(Command cancelCommand) {
			this.cancelCommand = cancelCommand;
		}
		public void setUpdateCommand(Command updateCommand) {
			this.updateCommand = updateCommand;
		}
		public void setCompleteCommand(Command completeCommand) {
			this.completeCommand = completeCommand;
		}
		public void setStartCommand(Command startCommand) {
			this.startCommand = startCommand;
		}
		public void setProgress(double progress) {
			this.progress = progress;
		}
	}
	
	
	public static class HiddenExt extends HTMLExt implements IHidden{

		private String name;
		private String value;

		public HiddenExt(String name) {
			this(name, null);
		}

		private void updateHtml() {
			setHTML("<input type=hidden "+(value != null ? "value=\""+value+"\" " : "") 
					+ (name != null ? "name="+name+" " : "")+">");
		}

		public HiddenExt(String name, String value) {
			this.name = name;
			this.value = value;
			updateHtml();
			getElement().getStyle().setProperty("display", "none");
		}

		public String getValue() {
			return value;
		}

		public void setValue(String value) {
			this.value = value;
			updateHtml();
		}

		public String getName() {
			return name;
		}

		public void setName(String name) {
			this.name = name;
			updateHtml();
		}
	}
	
	public static class ButtonExt extends Button implements IButton{
		public ButtonExt(String text) {
			super(text);
		}
	}
	
	public static class FormPanelExt extends FormPanel implements IFormPanel{

		public FormPanelExt() {
		}
		public FormPanelExt(String target) {
			super(target);
		}
	}
	
	public static class FocusPanelExt extends FocusPanel implements IFocusPanel{
		public void setIWidget(IWidget widget) {
			super.setWidget((Widget) widget);
		}
	}
	
	public static class HorizontalPanelExt extends HorizontalPanel implements IHorizontalPanel{
		public void add(IWidget widget) {
			super.add((Widget) widget);
		}
	}
	
	public static class ScrollPanelExt extends ScrollPanel implements IScrollPanel{

		public IWidget getIWidget() {
			return (IWidget) super.getWidget();
		}

		public void setWidget(IWidget widget) {
			super.setWidget((Widget) widget);
		}

		public void add(IWidget widget) {
			super.add((Widget) widget);
		}
	}
	
	public interface IPopupPanel extends IWidget{
		public void show();
		public void setPopupPositionAndShow(PositionCallback callback);
		public void hide();
		public void setPopupPosition(int x, int y);
	}
	
	public interface IFileUpload{
		public String getFilename();
	}
	
	public static class FileUploadExt extends FileUpload implements IFileUpload{
		
	}
	public static class PopupPanelExt extends PopupPanel implements IPopupPanel{

		public PopupPanelExt() {
		}
		public PopupPanelExt(boolean autoHide) {
			super(autoHide);
		}
	}
	
	public static class CheckBoxExt extends CheckBox implements SelectionInput{
		public CheckBoxExt(String text) {
			super(text, true);
		}

		public CheckBoxExt() {
			super();
		}
	}
	
	public static class CheckBoxEnable extends LazyWidget implements SelectionInput{
		private HTML overlay = new HTML("&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;");
		private CheckBoxExt checkBoxExt = new CheckBoxExt();
		private String text;
		public CheckBoxEnable(String text) {
			this.text = text;
		}
		public CheckBoxEnable() {
			text = "";
		}
		
		public void setEnabled(boolean enabled) {
			checkBoxExt.setEnabled(enabled);
			updateOverlayVisibility();
		}
		private void updateOverlayVisibility() {
			overlay.setVisible(!checkBoxExt.isEnabled());
		}
		public void addClickListener(ClickListener listener) {
			checkBoxExt.addClickListener(listener);
			overlay.addClickListener(listener);
		}
		@Override
		public Widget createContentWidget() {
			FlowPanel mainPanel = new FlowPanel();

			if(text != null)
				checkBoxExt.setHTML(text);
			
			addWidgetListener(new WidgetListenerAdapter(){
				@Override
				public void onAttach(IWidget arg0) {
					updateOverlayVisibility();
				}
			});
			mainPanel.add(checkBoxExt);
			mainPanel.add(overlay);
			
			getElement().getStyle().setProperty("position", "relative");
			getElement().getStyle().setProperty("overflow", "visible");
			getElement().getStyle().setProperty("display", "inline");
			setPixelSize(15, 15);
			mainPanel.getElement().getStyle().setProperty("display", "inline");
			checkBoxExt.getElement().getStyle().setProperty("display", "inline");
			overlay.getElement().getStyle().setProperty("position", "absolute");
			overlay.getElement().getStyle().setPropertyPx("top", 0);
			overlay.getElement().getStyle().setPropertyPx("left", 0);
			overlay.getElement().getStyle().setProperty("cursor", "default");
			overlay.setPixelSize(15, 15);
			return mainPanel;
		}
		public boolean isChecked() {
			return checkBoxExt.isChecked();
		}
		public void setChecked(boolean checked) {
			checkBoxExt.setChecked(checked);
		}
		public String getName() {
			return checkBoxExt.getName();
		}
		public void setName(String name) {
			checkBoxExt.setName(name);
		}
		public String getHTML() {
			return checkBoxExt.getHTML();
		}
		public void setHTML(String html) {
			checkBoxExt.setHTML(html);
		}
		public String getText() {
			return checkBoxExt.getText();
		}
		public void setText(String text) {
			checkBoxExt.setText(text);
		}
		public int getTabIndex() {
			return checkBoxExt.getTabIndex();
		}
		public void setAccessKey(char key) {
			checkBoxExt.setAccessKey(key);
		}
		public void setFocus(boolean focused) {
			checkBoxExt.setFocus(focused);
		}
		public void setTabIndex(int index) {
			checkBoxExt.setTabIndex(index);
		}
		public HandlerRegistration addClickHandler(ClickHandler handler) {
			overlay.addClickHandler(handler);
			return checkBoxExt.addClickHandler(handler);
		}
		public HandlerRegistration addKeyDownHandler(KeyDownHandler handler) {
			return checkBoxExt.addKeyDownHandler(handler);
		}
		public HandlerRegistration addKeyPressHandler(KeyPressHandler handler) {
			return checkBoxExt.addKeyPressHandler(handler);
		}
		public HandlerRegistration addKeyUpHandler(KeyUpHandler handler) {
			return checkBoxExt.addKeyUpHandler(handler);
		}
		public boolean isEnabled() {
			return checkBoxExt.isEnabled();
		}
		public HandlerRegistration addFocusHandler(FocusHandler handler) {
			return checkBoxExt.addFocusHandler(handler);
		}
		public HandlerRegistration addBlurHandler(BlurHandler handler) {
			return checkBoxExt.addBlurHandler(handler);
		}
	}
	
	public static class ImageExt extends Composite implements IImage{
		private Image image;
		private MediaPicture mediaPicture;
		DelegatingClickListenerCollection clickListenerCollection;
		public ImageExt(Image image) {
//			super(image.getElement());
			this.image = image;
			SimplePanel panel = new SimplePanel();
			initWidget(this.image);
			clickListenerCollection  = new DelegatingClickListenerCollection(this, image);
		}
		public ImageExt() {
			this(new Image());
//			super();
		}
		public ImageExt(String url) {
			this(new Image(url));
		}
		public void setUrl(String url) {
			image.setUrl(url);
		}
		public Image getImage() {
			return image;
		}
		@Override
		public void setVisible(boolean visible) {
			super.setVisible(visible);
			image.setVisible(visible);
		}
		public String getUrl() {
			return image.getUrl();
		}
		public MediaPicture getMediaPicture() {
			return mediaPicture;
		}
		public void setMediaPicture(MediaPicture mediaPicture, boolean showLowResolution) {
			this.mediaPicture = mediaPicture;
			if(showLowResolution)
				setUrl(mediaPicture.getLowResImage());
			else	
				setUrl(mediaPicture.getHighResImage());
		}
		public int getHeight() {
			return image.getHeight();
		}
		public int getWidth() {
			return image.getWidth();
		}
		public HandlerRegistration addLoadHandler(LoadHandler handler) {
			return image.addLoadHandler(handler);
		}
		public HandlerRegistration addErrorHandler(ErrorHandler handler) {
			return image.addErrorHandler(handler);
		}
		public HandlerRegistration addClickHandler(ClickHandler handler) {
			return image.addClickHandler(handler);
		}
		public HandlerRegistration addMouseDownHandler(MouseDownHandler handler) {
			return image.addMouseDownHandler(handler);
		}
		public HandlerRegistration addMouseUpHandler(MouseUpHandler handler) {
			return image.addMouseUpHandler(handler);
		}
		public HandlerRegistration addMouseOutHandler(MouseOutHandler handler) {
			return image.addMouseOutHandler(handler);
		}
		public HandlerRegistration addMouseOverHandler(MouseOverHandler handler) {
			return image.addMouseOverHandler(handler);
		}
		public HandlerRegistration addMouseMoveHandler(MouseMoveHandler handler) {
			return image.addMouseMoveHandler(handler);
		}
		public HandlerRegistration addMouseWheelHandler(MouseWheelHandler handler) {
			return image.addMouseWheelHandler(handler);
		}
	}
	
	public interface IDisclosurePanel extends ILazyWidget, FiresDisclosureEvents, HasWidgets, HasAnimation{

		boolean isOpen();
		
	}
	
	public static class DisclosurePanelExt extends LazyWidget implements IDisclosurePanel{

		private DisclosurePanel disclosurePanel;
		public DisclosurePanelExt(String header) {
			disclosurePanel = new DisclosurePanel(header);
		}

		@Override
		public Widget createContentWidget() {
			return disclosurePanel;
		}

		public void addEventHandler(DisclosureHandler handler) {
			disclosurePanel.addEventHandler(handler);
		}

		public void removeEventHandler(DisclosureHandler handler) {
			disclosurePanel.removeEventHandler(handler);
		}

		public void add(Widget w) {
			disclosurePanel.add(w);
		}

		public void clear() {
			disclosurePanel.clear();
		}

		public Iterator<Widget> iterator() {
			return disclosurePanel.iterator();
		}

		public boolean remove(Widget w) {
			return disclosurePanel.remove(w);
		}

		public boolean isAnimationEnabled() {
			return disclosurePanel.isAnimationEnabled();
		}

		public void setAnimationEnabled(boolean enable) {
			disclosurePanel.setAnimationEnabled(enable);
		}

		public void setContent(IWidget widget) {
			disclosurePanel.setContent((Widget) widget);
		}

		public boolean isOpen() {
			return disclosurePanel.isOpen();
		}
	}
	
	public static class InlineHTMLExt extends InlineHTML implements IHTML{
		private boolean enable = true;

		public InlineHTMLExt(String text) {
			super(text);
		}

		public InlineHTMLExt() {
			super();
		}

		public void setEnable(boolean enable) {
			this.enable = enable;
			updateStyleName();
		}
		private void updateStyleName() {
			setStyleName(getStylePrimaryName());
			if(!enable)
				addStyleDependentName("disabled");
		}
		public boolean isEnable() {
			return enable;
		}
	}
	
	public static class HTMLExt extends HTML implements IHTML{
		private boolean enable = true;

		public HTMLExt(String text) {
			super(text);
		}

		public HTMLExt() {
			super();
		}

		public void setEnable(boolean enable) {
			this.enable = enable;
			updateStyleName();
		}
		private void updateStyleName() {
			setStyleName(getStylePrimaryName());
			if(!enable)
				addStyleDependentName("disabled");
		}
		public boolean isEnable() {
			return enable;
		}
	}
	
	public static class TextBoxExt extends TextBox implements TextInput{
	}
	public static class DateBoxExt extends DateBox implements TextInput{
		public DateBoxExt() {
		}
		public DateBoxExt(DatePicker picker, Date date, Format format){
			super(picker, date, format);
		}
		public void selectAll() {
			getTextBox().selectAll();
		}
		public void setCursorPos(int pos) {
			getTextBox().setCursorPos(pos);
		}
		public String getText() {
			return getTextBox().getText();
		}
		public void setText(String text) {
			getTextBox().setText(text);
		}
		public String getName() {
			return getTextBox().getName();
		}

		public void setName(String name) {
			getTextBox().setName(name);
		}

		public HandlerRegistration addClickHandler(ClickHandler handler) {
			return getTextBox().addClickHandler(handler);
		}

		public HandlerRegistration addKeyDownHandler(KeyDownHandler handler) {
			return getTextBox().addKeyDownHandler(handler);
		}

		public HandlerRegistration addKeyPressHandler(KeyPressHandler handler) {
			return getTextBox().addKeyPressHandler(handler);
		}

		public HandlerRegistration addKeyUpHandler(KeyUpHandler handler) {
			return getTextBox().addKeyUpHandler(handler);
		}

		public HandlerRegistration addFocusHandler(FocusHandler handler) {
			return getTextBox().addFocusHandler(handler);
		}

		public HandlerRegistration addBlurHandler(BlurHandler handler) {
			return getTextBox().addBlurHandler(handler);
		}

		public HandlerRegistration addChangeHandler(ChangeHandler handler) {
			return getTextBox().addChangeHandler(handler);
		}
	}
	public static class TextAreaExt extends TextArea implements TextInput{
	}
	
	public static class RadioButtonExt extends RadioButton implements SelectionInput{
		public RadioButtonExt(String name) {
			super(name);
		}
		public RadioButtonExt(String name, String label) {
			super(name, label);
		}
		public RadioButtonExt(String name, String label, boolean asHTML) {
			super(name, label, asHTML);
		}
	}

	public static abstract class LazyWidget extends Composite implements Widgets.ILazyWidget{
		private SimplePanel mainPanel = new SimplePanel();
		private List<Widgets.WidgetListener> widgetListeners = new ArrayList<Widgets.WidgetListener>();
		private Widget contentWidget;
		public LazyWidget() {
			initWidget(mainPanel);
		}
		
		abstract public Widget createContentWidget();
		@Override
		protected void onAttach() {
			super.onAttach();
			updateContentWidget();
		}
		
		@Override
		protected void onDetach() {
			for (Widgets.WidgetListener widgetListener : widgetListeners) {
				widgetListener.onDetachBefore(this);
			}
			super.onDetach();
			for (Widgets.WidgetListener widgetListener : widgetListeners) {
				widgetListener.onDetach(this);
			}
		}
	
		private void updateContentWidget() {
			if(!isAttached() || !isVisible())
				return;
			Widget contentWidgetBefore = this.contentWidget;
				
			if(contentWidgetBefore == null){
				for (WidgetListener widgetListener : widgetListeners) {
					widgetListener.onInitBefore(this);
				}
				contentWidget = createContentWidget();
				if(contentWidgetBefore == null){
					for (Widgets.WidgetListener widgetListener : widgetListeners) {
						widgetListener.onInit(this);
					}
				}
			}
			
			if(!contentWidget.isAttached()){
				mainPanel.setWidget(contentWidget);
			}
			for (Widgets.WidgetListener widgetListener : widgetListeners) {
				widgetListener.onAttach(this);
			}
		}
	
		@Override
		public void setVisible(boolean visible) {
			boolean oldVisible = isVisible();
			super.setVisible(visible);
			if(oldVisible != visible)
				updateContentWidget();
		}
		
		public void addWidgetListener(Widgets.WidgetListener widgetListener){
			widgetListeners.add(widgetListener);
		}
		public void removeWidgetListener(Widgets.WidgetListener widgetListener){
			widgetListeners.remove(widgetListener);
		}
	}

	public interface WidgetListener{
		public void onInit(IWidget widget);

		public void onInitBefore(IWidget widget);

		public void onAttach(IWidget widget);
		
		public void onDetach(IWidget widget);
		
		public void onDetachBefore(IWidget widget);
	}
	
	public static class WidgetListenerAdapter implements WidgetListener{
		public void onInit(IWidget widget){
		}
		
		public void onInitBefore(IWidget widget) {
		}
		
		public void onAttach(IWidget widget) {
		}
		
		public void onDetach(IWidget widget) {
		}
		
		public void onDetachBefore(IWidget widget) {
		}
	}

	public interface ILazyWidget extends IWidget{
		public void addWidgetListener(Widgets.WidgetListener widgetListener);
		public void removeWidgetListener(Widgets.WidgetListener widgetListener);
	}

	
	public interface IListBox extends IFocusWidget, SourcesChangeEvents, HasName, HasChangeHandlers{
		public String getSelectedValue();		
		public String getSelectedItem();
		public int getSelectedIndex();
		public void setSelectedIndex(int selectedIndex);
		public void setItems(List<String> items, List<String> values);
		public void setSelectedItem(String name);
		public String getItemText(int index);
		public String getValue(int index);
		public void setItems(List<String> items);
		public int getItemCount();
	}

	public static class FrameExt extends Frame implements IFrame{

		private final String id;
		public FrameExt(String id) {
	         this.id = id;
			DOM.setElementAttribute(getElement(), "id", id);
		}
		public FrameExt(String id, String url) {
			super(url);
			this.id = id;
	         DOM.setElementAttribute(getElement(), "id", id);
		}
		public String getFrameUrl(){
			try{
				Document contentDocument = getFrameElement().getContentDocument();
				return contentDocument != null ? contentDocument.getURL() : getUrl();
//			String frameUrl = getFrameUrlPriv(id);
//			return frameUrl != null ? frameUrl : getUrl();
			}catch(Exception ex){
			}
			return getUrl();
		}
		private FrameElement getFrameElement() {
			return getElement().cast();
		}
		
		/*
		 * Due to the Same-Origin restriction this method will only return an url if called from the same url in the browser
		 */
	    public native String getFrameUrlPriv(String id) /*-{
			var content;
			var iframe = $doc.getElementById('"+id+"');
	        //contentDocument is Firefox, contentWindow is IE
	        if(iframe.contentDocument != undefined) {
	        	content = iframe.contentDocument;
	        } else {
	        	content = iframe.contentWindow;
	        }
	        var url = content.location.href;
	        return url;
	  }-*/;
	}

	public void onModuleLoad() {
		StyleInjector.injectStylesheet(WidgetsResources.INSTANCE.css().getText());
	}
	
}
